package com.app.stick.device.service.impl;

import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import com.app.common.constant.CacheConstants;
import com.app.common.core.redis.RedisCache;
import com.app.common.enums.DeleteEnum;
import com.app.common.enums.EnableEnum;
import com.app.common.enums.sick.PdiBindStatusEnum;
import com.app.common.exception.ServiceException;
import com.app.common.utils.DateUtils;
import com.app.common.utils.SecurityUtils;
import com.app.common.utils.StringUtils;
import com.app.stick.bind.domain.BizPatientDeviceInfo;
import com.app.stick.bind.mapper.BizPatientDeviceInfoMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.app.stick.device.mapper.BizDeviceInfoMapper;
import com.app.stick.device.domain.BizDeviceInfo;
import com.app.stick.device.service.IBizDeviceInfoService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

/**
 * 设备信息Service业务层处理
 *
 * @author app
 * @date 2023-12-16
 */
@Service
public class BizDeviceInfoServiceImpl extends ServiceImpl<BizDeviceInfoMapper, BizDeviceInfo> implements IBizDeviceInfoService
{
    @Resource
    private BizDeviceInfoMapper bizDeviceInfoMapper;

    @Resource
    private BizPatientDeviceInfoMapper bizPatientDeviceInfoMapper;

    @Autowired
    private RedisCache redisCache;

    @PostConstruct
    public void init(){
        loadingDeviceCache();
    }


    /**
     * 加载设备缓存数据
     */
    @Override
    public void loadingDeviceCache() {
        List<BizDeviceInfo> list = bizDeviceInfoMapper.selectList(new LambdaQueryWrapper<BizDeviceInfo>()
                .eq(BizDeviceInfo::getDelFlag, DeleteEnum.NO.getCode())
                .eq(BizDeviceInfo::getDeviceStatus, EnableEnum.YES.getCode()));
        for (BizDeviceInfo bizDeviceInfo : list) {
            redisCache.setCacheObject(getCacheKey(bizDeviceInfo.getDeviceMac()), bizDeviceInfo.getDeviceCode());
        }
    }

    /**
     * 清空设备缓存数据
     */
    @Override
    public void clearConfigCache() {
        Collection<String> keys = redisCache.keys(CacheConstants.BIZ_DEVICE_KEY + "*");
        redisCache.deleteObject(keys);
    }

    /**
     * 重置设备缓存数据
     */
    @Override
    public void resetConfigCache() {
        clearConfigCache();
        loadingDeviceCache();
    }

    /**
     * 设置cache key
     *
     * @param configKey 参数键
     * @return 缓存键key
     */
    private String getCacheKey(String configKey)
    {
        return CacheConstants.BIZ_DEVICE_KEY + configKey;
    }

    /**
     * 查询设备信息
     *
     * @param deviceId 设备信息主键
     * @return 设备信息
     */
    @Override
    public BizDeviceInfo selectBizDeviceInfoByDeviceId(String deviceId)
    {
        return bizDeviceInfoMapper.selectById(deviceId);
    }

    /**
     * 查询设备信息列表
     *
     * @param bizDeviceInfo 设备信息
     * @return 设备信息
     */
    @Override
    public List<BizDeviceInfo> selectBizDeviceInfoList(BizDeviceInfo bizDeviceInfo)
    {
        bizDeviceInfo.setDelFlag(DeleteEnum.NO.getCode());
        return bizDeviceInfoMapper.selectBizDeviceInfoList(bizDeviceInfo);
    }

    /**
     * 新增设备信息
     *
     * @param bizDeviceInfo 设备信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertBizDeviceInfo(BizDeviceInfo bizDeviceInfo)
    {
        //先判断编号和mac地址是否重复
        if (StringUtils.isEmpty(bizDeviceInfo.getDeviceCode())) {
            throw new ServiceException("设备编号不能为空");
        }
        if (StringUtils.isEmpty(bizDeviceInfo.getDeviceMac())) {
            throw new ServiceException("设备mac地址不能为空");
        }
        long deviceCodeNum = bizDeviceInfoMapper.selectCount(new LambdaQueryWrapper<BizDeviceInfo>()
                .eq(BizDeviceInfo::getDeviceCode, bizDeviceInfo.getDeviceCode())
                .eq(BizDeviceInfo::getDelFlag, DeleteEnum.NO.getCode()));
        if (deviceCodeNum > 0) {
            throw new ServiceException("设备编号不能重复");
        }
        long deviceMacNum = bizDeviceInfoMapper.selectCount(new LambdaQueryWrapper<BizDeviceInfo>()
                .eq(BizDeviceInfo::getDeviceMac, bizDeviceInfo.getDeviceMac())
                .eq(BizDeviceInfo::getDelFlag, DeleteEnum.NO.getCode()));
        if (deviceMacNum > 0) {
            throw new ServiceException("设备mac地址不能重复");
        }
        bizDeviceInfo.setDeviceNum(0L);
        bizDeviceInfo.setDeviceStatus(EnableEnum.YES.getCode());
        bizDeviceInfo.setDelFlag(DeleteEnum.NO.getCode());
        bizDeviceInfo.setCreateBy(SecurityUtils.getUserId());
        bizDeviceInfo.setCreateTime(DateUtils.getNowDate());
        bizDeviceInfo.setUpdateBy(SecurityUtils.getUserId());
        bizDeviceInfo.setUpdateTime(new Date());
        int insertDevice = bizDeviceInfoMapper.insert(bizDeviceInfo);
        if (insertDevice <= 0) {
            throw new ServiceException("新增设备信息失败");
        }
        redisCache.setCacheObject(getCacheKey(bizDeviceInfo.getDeviceMac()), bizDeviceInfo.getDeviceCode());
        return insertDevice;
    }

    /**
     * 修改设备信息
     *
     * @param bizDeviceInfo 设备信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateBizDeviceInfo(BizDeviceInfo bizDeviceInfo)
    {
        //判断是否传入设备ID
        if (StringUtils.isEmpty(bizDeviceInfo.getDeviceId())) {
            throw new ServiceException("设备ID不能为空");
        }
        BizDeviceInfo deviceInfo = bizDeviceInfoMapper.selectById(bizDeviceInfo.getDeviceId());
        if (StringUtils.isNull(deviceInfo)) {
            throw new ServiceException("未查询到设备信息");
        }
        //先判断编号和mac地址是否重复
        if (StringUtils.isNotEmpty(bizDeviceInfo.getDeviceCode()) || StringUtils.isNotEmpty(bizDeviceInfo.getDeviceMac())) {
            //判断设备是否被绑定
            long bindDeviceNum = bizPatientDeviceInfoMapper.selectCount(new LambdaQueryWrapper<BizPatientDeviceInfo>()
                    .eq(BizPatientDeviceInfo::getDeviceCode, deviceInfo.getDeviceCode())
                    .eq(BizPatientDeviceInfo::getPdiBindStatus, PdiBindStatusEnum.BIND.getCode())
                    .eq(BizPatientDeviceInfo::getDelFlag, DeleteEnum.NO.getCode()));
            if (bindDeviceNum > 0) {
                throw new ServiceException("该设备处于绑定状态,不能修改");
            }
            if (StringUtils.isNotEmpty(bizDeviceInfo.getDeviceCode())) {
                long deviceCodeNum = bizDeviceInfoMapper.selectCount(new LambdaQueryWrapper<BizDeviceInfo>()
                        .ne(BizDeviceInfo::getDeviceId, bizDeviceInfo.getDeviceId())
                        .eq(BizDeviceInfo::getDeviceCode, bizDeviceInfo.getDeviceCode())
                        .eq(BizDeviceInfo::getDelFlag, DeleteEnum.NO.getCode()));
                if (deviceCodeNum > 0) {
                    throw new ServiceException("设备编号不能重复");
                }
            }
            if (StringUtils.isNotEmpty(bizDeviceInfo.getDeviceMac())) {
                long deviceMacNum = bizDeviceInfoMapper.selectCount(new LambdaQueryWrapper<BizDeviceInfo>()
                        .ne(BizDeviceInfo::getDeviceId, bizDeviceInfo.getDeviceId())
                        .eq(BizDeviceInfo::getDeviceMac, bizDeviceInfo.getDeviceMac())
                        .eq(BizDeviceInfo::getDelFlag, DeleteEnum.NO.getCode()));
                if (deviceMacNum > 0) {
                    throw new ServiceException("设备mac地址不能重复");
                }

                if (!StringUtils.equals(deviceInfo.getDeviceMac(), bizDeviceInfo.getDeviceMac())) {
                    redisCache.deleteObject(getCacheKey(deviceInfo.getDeviceMac()));
                }
            }
        }
        bizDeviceInfo.setUpdateBy(SecurityUtils.getUserId());
        bizDeviceInfo.setUpdateTime(new Date());
        int updateDevice = bizDeviceInfoMapper.updateBizDeviceInfo(bizDeviceInfo);
        if (updateDevice <= 0) {
            throw new ServiceException("设备信息修改失败");
        }
        redisCache.setCacheObject(getCacheKey(bizDeviceInfo.getDeviceMac()), bizDeviceInfo.getDeviceCode());
        return updateDevice;
    }

    /**
     * 批量删除设备信息
     *
     * @param deviceIds 需要删除的设备信息主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteBizDeviceInfoByDeviceIds(String[] deviceIds)
    {
        for (String deviceId : deviceIds) {
            BizDeviceInfo deviceInfo = bizDeviceInfoMapper.selectById(deviceId);
            if (StringUtils.isNull(deviceInfo)) {
                throw new ServiceException("未查询到设备信息");
            }
            //判断设备是否被绑定
            long bindDeviceNum = bizPatientDeviceInfoMapper.selectCount(new LambdaQueryWrapper<BizPatientDeviceInfo>()
                    .eq(BizPatientDeviceInfo::getDeviceCode, deviceInfo.getDeviceCode())
                    .eq(BizPatientDeviceInfo::getPdiBindStatus, PdiBindStatusEnum.BIND.getCode())
                    .eq(BizPatientDeviceInfo::getDelFlag, DeleteEnum.NO.getCode()));
            if (bindDeviceNum > 0) {
                throw new ServiceException("该设备处于绑定状态,不能删除");
            }
            BizDeviceInfo bizDeviceInfo = new BizDeviceInfo();
            bizDeviceInfo.setDeviceId(deviceId);
            bizDeviceInfo.setDelFlag(DeleteEnum.YES.getCode());
            bizDeviceInfo.setUpdateBy(SecurityUtils.getUserId());
            bizDeviceInfo.setUpdateTime(new Date());
            int deleteDevice = bizDeviceInfoMapper.updateById(bizDeviceInfo);
            if (deleteDevice <= 0){
                throw new ServiceException("设备删除失败,请重试");
            }
            redisCache.deleteObject(getCacheKey(deviceInfo.getDeviceMac()));
        }
        return 1;
    }

    /**
     * 删除设备信息信息
     *
     * @param deviceId 设备信息主键
     * @return 结果
     */
    @Override
    public int deleteBizDeviceInfoByDeviceId(String deviceId)
    {
        BizDeviceInfo deviceInfo = bizDeviceInfoMapper.selectById(deviceId);
        if (StringUtils.isNull(deviceInfo)) {
            throw new ServiceException("未查询到设备信息");
        }
        //判断设备是否被绑定
        long bindDeviceNum = bizPatientDeviceInfoMapper.selectCount(new LambdaQueryWrapper<BizPatientDeviceInfo>()
                .eq(BizPatientDeviceInfo::getDeviceCode, deviceInfo.getDeviceCode())
                .eq(BizPatientDeviceInfo::getPdiBindStatus, PdiBindStatusEnum.BIND.getCode())
                .eq(BizPatientDeviceInfo::getDelFlag, DeleteEnum.NO.getCode()));
        if (bindDeviceNum > 0) {
            throw new ServiceException("该设备处于绑定状态,不能删除");
        }
        BizDeviceInfo bizDeviceInfo = new BizDeviceInfo();
        bizDeviceInfo.setDeviceId(deviceId);
        bizDeviceInfo.setDelFlag(DeleteEnum.YES.getCode());
        bizDeviceInfo.setUpdateBy(SecurityUtils.getUserId());
        bizDeviceInfo.setUpdateTime(new Date());
        int deleteDevice = bizDeviceInfoMapper.updateById(bizDeviceInfo);
        if (deleteDevice <= 0) {
            throw new ServiceException("设备删除失败,请重试");
        }
        redisCache.deleteObject(getCacheKey(deviceInfo.getDeviceMac()));
        return deleteDevice;
    }

    /**
     * 修改设备状态
     * @param bizDeviceInfo
     * @return int
     */
    @Override
    public int changeStatus(BizDeviceInfo bizDeviceInfo) {
        //判断是否传入设备ID
        if (StringUtils.isEmpty(bizDeviceInfo.getDeviceId())) {
            throw new ServiceException("设备ID不能为空");
        }
        BizDeviceInfo deviceInfo = bizDeviceInfoMapper.selectById(bizDeviceInfo.getDeviceId());
        if (StringUtils.isNull(deviceInfo)) {
            throw new ServiceException("未查询到设备信息");
        }
        //判断设备是否被绑定
        long bindDeviceNum = bizPatientDeviceInfoMapper.selectCount(new LambdaQueryWrapper<BizPatientDeviceInfo>()
                .eq(BizPatientDeviceInfo::getDeviceCode, deviceInfo.getDeviceCode())
                .eq(BizPatientDeviceInfo::getPdiBindStatus, PdiBindStatusEnum.BIND.getCode())
                .eq(BizPatientDeviceInfo::getDelFlag, DeleteEnum.NO.getCode()));
        if (bindDeviceNum > 0) {
            throw new ServiceException("该设备处于绑定状态,不能修改状态");
        }
        bizDeviceInfo.setUpdateBy(SecurityUtils.getUserId());
        bizDeviceInfo.setUpdateTime(new Date());
        int updateDevice = bizDeviceInfoMapper.updateById(bizDeviceInfo);
        if (updateDevice <= 0) {
            throw new ServiceException("设备状态修改失败");
        }
        return updateDevice;
    }
}
